package emumTest;

import java.util.Random;

/**
 * @ClassName EnumTest3
 * @Description
 * 解决上面问题的办法就是多路分发(在那个例子中, 只有两个分发, 一般称之为两路分发)。
 * 多态只能发生在方法调用时,所以,如果你想使用两路分发,那么就必须有两个方法调用:第
 * 一个方法调用决定第一个未知类型,第二个方法调用决定第二个未知的类型。要利用多路分发,
 * 程序员必须为每一个类型提供一个实际的方法调用,如果你要处理两个不同的类型体系,就需
 * 要为每个类型体系执行一个方法调用。一般而言,程序员需要有设定好的某种配置,以便一个
 * 方法调用能够引出更多的方法调用,从而能够在这个过程中处理多种类型。为了达到这种效果
 * 我们需要与多个方法一同工作:因为每个分发都需要一个方法调用。在下面的例子中(实现了
 * “石头、剪刀、布”游戏,也称为 RoShamBo)对应的方法是 competeD和evaO,二者都是同一个
 * 类型的成员,它们可以产生三种 Outcome实例中的一个作为结果e
 * @Author LIBOFEI
 * @Date 2020/6/7 13:37
 * @Version 1.0
 **/
enum OutCome{
    WIN,
    LOSE,
    DRAW
}
interface Item{
    OutCome compete(Item item);
    OutCome eval(Paper p);
    OutCome eval(Scissor s);
    OutCome eval(Rock r);
}
class Paper implements Item{
    @Override
    public OutCome compete(Item item) {
        return item.eval(this);
    }

    @Override
    public OutCome eval(Paper p) {
        return OutCome.DRAW;
    }

    @Override
    public OutCome eval(Scissor s) {
        return OutCome.WIN;
    }

    @Override
    public OutCome eval(Rock r) {
        return OutCome.LOSE;
    }

    @Override
    public String toString() {
        return "Paper";
    }
}

class Scissor implements Item{
    @Override
    public OutCome compete(Item item) {
        return item.eval(this);
    }

    @Override
    public OutCome eval(Paper p) {
        return OutCome.LOSE;
    }

    @Override
    public OutCome eval(Scissor s) {
        return OutCome.DRAW;
    }

    @Override
    public OutCome eval(Rock r) {
        return OutCome.WIN;
    }

    @Override
    public String toString() {
        return "Scissor";
    }
}

class Rock implements Item{
    @Override
    public OutCome compete(Item item) {
        return item.eval(this);
    }

    @Override
    public OutCome eval(Paper p) {
        return OutCome.WIN;
    }

    @Override
    public OutCome eval(Scissor s) {
        return OutCome.LOSE;
    }

    @Override
    public OutCome eval(Rock r) {
        return OutCome.DRAW;
    }
    @Override
    public String toString() {
        return "Rock";
    }
}
public class EnumTest3 {

    static final int size = 20;
    private static Random random = new Random(47);

    public static Item newItem() {
        switch (random.nextInt(3)){
            case 0:
                return new Scissor();
            case 1:
                return new Paper();
            case 2:
                return new Rock();
            default:
                return null;
        }
    }

    public static void match(Item a ,Item b) {
        System.out.println(a + " vs " + b + a.compete(b));
    }

    public static void main(String[] args) {
        for(int i = 0; i < size ; i++){
            match(newItem(),newItem());
        }
    }


}
